/*
 *    Copyright (c) 2018-2025, boss All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the boss developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: boss
 */
package com.hopes.bizz.risk.transfer.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hopes.bizz.common.core.util.StringUtils;
import com.hopes.bizz.risk.transfer.bean.entity.RiskTransferAuthEntity;
import com.hopes.bizz.risk.transfer.bean.entity.RiskTransferDataEntity;
import com.hopes.bizz.risk.transfer.bean.entity.RiskTransferErrorLogEntity;
import com.hopes.bizz.risk.transfer.bean.entity.RiskTransferLogEntity;
import com.hopes.bizz.risk.transfer.bean.log.dto.RiskErrorLogDTO;
import com.hopes.bizz.risk.transfer.bean.log.dto.RiskLogDTO;
import com.hopes.bizz.risk.transfer.bean.log.vo.RiskErrorLogVo;
import com.hopes.bizz.risk.transfer.bean.log.vo.RiskLogVo;
import com.hopes.bizz.risk.transfer.bean.vo.RiskDataReportStatistics;
import com.hopes.bizz.risk.transfer.mapper.RiskTransferLogMapper;
import com.hopes.bizz.risk.transfer.service.RiskTransferAuthService;
import com.hopes.bizz.risk.transfer.service.RiskTransferDataService;
import com.hopes.bizz.risk.transfer.service.RiskTransferErrorLogService;
import com.hopes.bizz.risk.transfer.service.RiskTransferLogService;
import com.hopes.boss.admin.api.entity.SysDictItem;
import com.hopes.boss.admin.api.resolver.DictResolver;
import com.hopes.boss.admin.api.resolver.enums.AdminDictEnum;
import com.hopes.boss.admin.api.resolver.enums.AdminEnums;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 风险数据对接日志
 *
 * @author pig
 * @date 2024-02-01 20:17:10
 */
@Service
@Slf4j
@AllArgsConstructor
public class RiskTransferLogServiceImpl extends ServiceImpl<RiskTransferLogMapper, RiskTransferLogEntity> implements RiskTransferLogService {

    private final RiskTransferErrorLogService riskTransferErrorLogService;

    private final RiskTransferAuthService riskTransferAuthService;

    private final RiskTransferDataService riskTransferDataService;

    @Override
    public List<RiskLogVo> getLog(RiskLogDTO riskDataDto) {
        List<String> batchIdList = riskDataDto.getBatchId();
        List<RiskLogVo> res = new ArrayList<>();
        for (String batchId : batchIdList) {
            RiskTransferLogEntity riskTransferLogEntity = getByBatchId(batchId);
            if (Objects.isNull(riskTransferLogEntity)) {
                continue;
            }
            RiskLogVo riskLogVo = new RiskLogVo();
            riskLogVo.setBatchId(batchId);
            riskLogVo.setErrorIdStr(riskTransferLogEntity.getErrorId());
            riskLogVo.setStatus(riskTransferLogEntity.getStatus().toString());
            riskLogVo.setErrorCount(riskTransferLogEntity.getErrorCount());
            riskLogVo.setTotalCount(riskTransferLogEntity.getTotalCount());
            res.add(riskLogVo);
        }
        return res;
    }

    @Override
    public RiskTransferLogEntity getByBatchId(String batchId) {
        if (StringUtils.isBlank(batchId)) return null;
        return lambdaQuery().eq(RiskTransferLogEntity::getBatchId, batchId).one();
    }

    @Override
    public List<RiskErrorLogVo> getErrorLog(RiskErrorLogDTO riskErrorLogDTO) {
        List<String> errorIds = riskErrorLogDTO.getErrorIds();
        List<RiskErrorLogVo> res = new ArrayList<>();
        for (String errorId : errorIds) {
            RiskTransferErrorLogEntity riskTransferErrorLog = riskTransferErrorLogService.getByErrorId(errorId);
            if (Objects.isNull(riskTransferErrorLog)) {
                continue;
            }
            RiskErrorLogVo riskErrorLogVo = buildErrorLog(riskTransferErrorLog);
            res.add(riskErrorLogVo);
        }
        return res;
    }

    @Override
    public RiskDataReportStatistics calculateRiskDataReport() {
        RiskDataReportStatistics riskDataReportStatistics = new RiskDataReportStatistics();
        // 企业总数
        List<SysDictItem> orgItem = DictResolver.getItemsByType(AdminDictEnum.sys_company);
        riskDataReportStatistics.setTotalOrgCount(orgItem.size());

        // 双重预防机制应接入企业
        Long expectedOrgIngestionRiskDataCount = riskTransferAuthService.lambdaQuery()
                .eq(RiskTransferAuthEntity::getUse, Boolean.TRUE)
                .count();
        riskDataReportStatistics.setExpectedOrgIngestionRiskDataCount(expectedOrgIngestionRiskDataCount.intValue());

        //今日已上报数据企业
        Long todayReportedDataOrgCount = this.lambdaQuery()
                .ge(RiskTransferLogEntity::getRequestTime, DateUtil.beginOfDay(new Date()))
                .select(RiskTransferLogEntity::getOrgId)
                .list().stream().map(RiskTransferLogEntity::getOrgId).distinct().count();
        riskDataReportStatistics.setTodayReportedDataOrgCount(todayReportedDataOrgCount.intValue());

        //今日未上报数据企业
        long todayUnReportDataOrgCount = expectedOrgIngestionRiskDataCount - todayReportedDataOrgCount;
        riskDataReportStatistics.setTodayUnReportDataOrgCount((int) todayUnReportDataOrgCount);

        //今日企业数据接入率
        if (expectedOrgIngestionRiskDataCount > 0) {
            double todayDeptRiskDataIngestionRate = NumberUtil.div(todayReportedDataOrgCount, expectedOrgIngestionRiskDataCount, 2).doubleValue();
            riskDataReportStatistics.setTodayOrgRiskDataIngestionRate(todayDeptRiskDataIngestionRate);
        }
        return riskDataReportStatistics;
    }

    @Override
    public String getReportDataByBatchId(String batchId) {
        RiskTransferDataEntity transferData = riskTransferDataService.lambdaQuery()
                .eq(RiskTransferDataEntity::getBatchId, batchId)
                .select(RiskTransferDataEntity::getDecryptData)
                .one();
        return Optional.ofNullable(transferData).map(RiskTransferDataEntity::getDecryptData).orElse(null);
    }

    private static RiskErrorLogVo buildErrorLog(RiskTransferErrorLogEntity riskTransferErrorLog) {
        RiskErrorLogVo riskErrorLogVo = new RiskErrorLogVo();
        riskErrorLogVo.setBatchId(riskTransferErrorLog.getBatchId());
        riskErrorLogVo.setCompanyCode(riskTransferErrorLog.getCompanyCode());
        riskErrorLogVo.setId(riskTransferErrorLog.getErrorId());
        riskErrorLogVo.setRequestType(riskTransferErrorLog.getRequestType().toString());
        riskErrorLogVo.setFailReason(riskTransferErrorLog.getFailReason());
        riskErrorLogVo.setReceiveData(riskTransferErrorLog.getReceiveData());
        riskErrorLogVo.setResultTime(DateUtil.formatLocalDateTime(riskTransferErrorLog.getResultTime()));
        return riskErrorLogVo;
    }
}